package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import java.util.List;
import java.util.Properties;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;

/**
 * Nacos配置类
 */
@Configuration
@EnableConfigurationProperties(NacosPropertiesConfiguration.class)
public class NacosConfiguration {

	/**
	 * Converter转换器，将FlowRuleEntity转换成FlowRule
	 *
	 * @return
	 */
	@Bean
	public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	/**
	 * Converter反向转换器，将FlowRule转换成FlowRuleEntity
	 *
	 * @return
	 */
	@Bean
	public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
		return s -> JSON.parseArray(s, FlowRuleEntity.class);
	}

	@Bean
	public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
		return s -> JSON.parseArray(s, DegradeRuleEntity.class);
	}

	@Bean
	public Converter<String, List<AuthorityRuleEntity>> authorityRuleEntityDecoder() {
		return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
	}

	@Bean
	public Converter<List<AuthorityRuleEntity>, String> authorityRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
		return s -> JSON.parseArray(s, SystemRuleEntity.class);
	}

	@Bean
	public Converter<List<SystemRuleEntity>, String> systemRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleEntityDecoder() {
		return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
	}

	@Bean
	public Converter<List<ParamFlowRuleEntity>, String> paramFlowRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
		return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
	}

	@Bean
	public Converter<List<ApiDefinitionEntity>, String> gatewayApiDefinitionEntityEncoder() {
		// return JSON::toJSONString;
		return s -> JSON.toJSONString(s, true);
	}

	@Bean
	public Converter<String, List<ApiDefinitionEntity>> gatewayApiDefinitionEntityDecoder() {
		return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
	}

	/**
	 * Nacos配置服务
	 *
	 * @param nacosPropertiesConfiguration
	 * @return
	 * @throws NacosException
	 */
	@Bean
	public ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration) throws NacosException {
		Properties properties = new Properties();
		properties.put(PropertyKeyConst.SERVER_ADDR, nacosPropertiesConfiguration.getServerAddr());
		properties.put(PropertyKeyConst.NAMESPACE, nacosPropertiesConfiguration.getNamespace());
		return ConfigFactory.createConfigService(properties);
	}
}
